package class8;

class test1
{
    //static 静态的，属于类的
    //非static 非静态的，属于对象的
    int a=10;//非静态成员变量，属于对象的
    static int b=0;//静态成员变量，属于类的
    //其中每创建一个对象，都有一个a，但是只有一个b
    //1. 类加载与方法区
    //当 Java 程序运行时，首先会进行类的加载过程。类的相关信息，包括类的结构（如成员变量、方法等）会被加载到方法区中。
    //2. 类变量在堆内存中的存储
    //虽然类变量的声明信息在方法区，但实际的类变量存储位置在堆内存中。当类被实例化对象之前，类变量就已经在堆内存中分配好了空间。所有该类的实例对象共享这一份类变量的内存空间。
    //3. 栈内存与类变量的关系
    //栈内存主要用于存储方法中的局部变量和对象引用等。当方法执行时，局部变量会在栈内存中创建和销毁。对于类变量，栈内存中的对象引用可以用来访问堆内存中的类变量。
    //4. 类变量的初始化
    //类变量在类加载过程中会先进行默认初始化，比如int类型的类变量默认初始化为0，String类型默认初始化为null。

    public void print()
    {
        //实例方法可以访问非静态成员变量和静态成员变量
        System.out.println(a);
        System.out.println(b);
        //this可以出现在实例方法中，代表当前对象
    }
    static public void staticPrint()
    {
        //类方法只能访问静态成员变量，不能访问非静态成员变量
        //System.out.println(a);//错误，静态方法不能访问非静态成员变量
        System.out.println(b);
        //this不能出现在类方法中，因为类方法不属于某个对象
    }

    //工具类的一般建议直接使用类名调用，所以将构造函数私有化
    public test1()//private test1()一般建议这样定义
    {
        b++;//每创建一个对象，静态成员变量b加1,这便是静态成员变量的应用
    }


}

class test2
{
    static String str;
    int number;
    //介绍静态代码块与非静态代码块
    static
    {
        //静态代码块在类加载时执行，并且只执行一次
        System.out.println("静态代码块");
        str="Hello,Java!";//静态代码块中可以初始化静态成员变量
//        number=10;//错误，静态代码块不能访问非静态成员变量
    }
    {
        //非静态代码块在每次创建对象时执行，并且在构造函数之前执行
        System.out.println("非静态代码块");
        str="Hello,Java!";//非静态代码块可以访问静态成员变量
        number=10;//非静态代码块可以访问非静态成员变量
    }
}

class test3
{
    //单例模式
//    private static test3 instance=new test3();//饿汉式
    private static test3 instance=null;//懒汉式
    private test3()//私有化构造函数
    {

    }
    public static test3 getInstance()
    {
        //懒汉式
        if(instance==null)
        {
            instance=new test3();
        }
        return instance;
    }
}
public class oop_1
{
    public static void main(String[] args) {
        test1.b=30;//通过类名访问静态成员变量
//      test1.a=40;//错误，不能通过类名访问非静态成员变量
        test1 arr=new test1();
        arr.a=10;//通过对象访问非静态成员变量,不推荐！

        test1.staticPrint();//通过类名访问静态成员方法
        arr.print();//通过对象访问非静态成员方法,不推荐！
        //---------------------------------------------------------------
        test2 obj1=new test2();
        test2 obj2=new test2();
        //静态代码块只执行一次，非静态代码块每次创建对象都会执行

    }
}
